package com.cpr.core.concurrency;

import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

/**
 * @author Chen Panrui
 * created at 2022/1/6 10:23
 * 文档: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
 * Q: sleep方法为什么要 throws InterruptedException（困扰我已久的一个问题）?
 * A: Many methods that throw InterruptedException, such as sleep, are designed to cancel their current operation and return immediately when an interrupt is received.
 *
 * Q: Thread.interrupted静态方法 和 isInterrupted非静态方法的区别
 * A: The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking Thread.interrupt sets this flag.
 * When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared.
 * The non-static isInterrupted method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.
 */
public class Interrupts {

    @Getter
    @Setter
    @NoArgsConstructor
    static class MyThread extends Thread{

        private int interruptModel = 0;
        private int printCount = 10000;
        @Override
        public void run() {
            for (int i = 0; i < printCount; i++) {
                if(interruptModel == 0){
                    System.out.println("子线程:我在干活... i=" + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("子线程:我被中断了,不能再继续干活了!");
                        return;
                    }
                } else if(interruptModel == 1){
                    System.out.println("子线程:我在干活... i=" + i + "，中断状态=" + Thread.currentThread().isInterrupted());
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // sleep 会捕获&&处理掉 这个interrupt，所以此时应该重新打一个interrupt标志位，为了让后续流程可以监听到中断标志
                        e.printStackTrace();
                        interrupt();
                    }
                    if(Thread.currentThread().isInterrupted()){
                        System.out.println("子线程:我被中断了,不能再继续干活了!");
                        /*
                         * 非静态的方法，不会把线程设置的interrupt标志位改成 false，一直都是true
                         */
                        System.out.print("非静态interrupt状态=" + Thread.currentThread().isInterrupted());
                        /*
                         * 静态的方法，同时会把线程设置的interrupt标志位改成 false
                         */
                        System.out.print("，静态interrupt状态=" + Thread.interrupted());
                        System.out.print("，非静态interrupt状态=" + Thread.currentThread().isInterrupted());
                        System.out.print("，静态interrupt状态=" + Thread.interrupted());
                        return;
                    }
                }
            }
        }

        public MyThread(int interruptModel){
            this.interruptModel = interruptModel;
        }
    }

    public static void main(String[] args) throws InterruptedException {
        System.out.println("主线程: 我启动了一个子线程，5s后我再停止这个线程!");
        Thread t = new MyThread(1);
        t.start();
        Thread.sleep(5000);
        t.interrupt();
    }
}
